Skip to content

v2.19.0#273

Merged
HACO8888 merged 25 commits into
mainfrom
development
Apr 7, 2026
Merged

v2.19.0#273
HACO8888 merged 25 commits into
mainfrom
development

Conversation

@HACO8888
Copy link
Copy Markdown
Member

@HACO8888 HACO8888 commented Apr 6, 2026

No description provided.

OnCloud125252 and others added 2 commits March 8, 2026 14:01
- refactor version fetching to use a dedicated API endpoint
- add validation functions for ObjectId and custom IDs
- improve URL sanitization to prevent path traversal
- implement AbortController in data fetching hooks to prevent memory leaks
- update component structure for better readability and maintainability
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps the frontend to v2.19.0 and focuses on security/stability improvements (moving GitHub token usage server-side, adding input validation/sanitization, and reducing client-side fetch memory leaks via AbortController), plus a new in-app changelog page.

Changes:

  • Add validation utilities and apply URL param sanitization + stricter ID validation in routing.
  • Introduce /api/version and refactor online-version fetching to avoid exposing GitHub tokens in client code.
  • Add a Changelog page (desktop/mobile) backed by a JSON changelog; add broader AbortController usage across fetches.

Reviewed changes

Copilot reviewed 75 out of 75 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
utils/useUserAccount/index.ts Import reordering.
utils/usePost/index.ts Import reordering.
utils/useLocalStorage/index.tsx Import reordering.
utils/useFetch/index.ts Adds abort + mounted-guard behavior to useFetch.
package.json Version bump to 2.19.0.
modules/validation/index.ts New shared validators + URL param sanitization helpers.
modules/sigAPI/index.ts Import reordering.
modules/sigAPI/function/getUserData.ts Adds optional AbortSignal support.
modules/sigAPI/function/getSigData.ts Adds optional AbortSignal support.
modules/sigAPI/function/_request.ts Extends request option typing to allow signal.
modules/api/GetOnlineAppVersion/index.ts Refactors to client-side fetch from /api/version.
components/Threads/mobile/ThreadsList.tsx Import reordering.
components/Threads/desktop/ThreadsList.tsx Import reordering.
components/PostEditor/mobile/PostEditor.tsx Import reordering.
components/PostEditor/mobile/MetaDataForm.tsx Import reordering.
components/PostEditor/mobile/Editor.tsx Import reordering.
components/PostEditor/desktop/TitleSigForm.tsx Import reordering / type-only import adjustments.
components/PostEditor/desktop/PostEditor.tsx Import grouping changes.
components/PostEditor/desktop/MetaDataForm.tsx Import reordering.
components/PostEditor/desktop/Editor.tsx Import reordering.
components/NotFound/index.tsx Import reordering.
app/providers.tsx Import reordering.
app/post/[postID]/page.tsx Adds param sanitization + ObjectId validation + abort on fetch.
app/post/[postID]/edit/page.tsx Import reordering.
app/post/[postID]/(post)/mobile/Thread.tsx Import reordering.
app/post/[postID]/(post)/mobile/Replies.tsx Import reordering.
app/post/[postID]/(post)/desktop/ThreadInfo.tsx Adds mounted-guard + abort controller for fetches.
app/post/[postID]/(post)/desktop/Thread.tsx Import reordering.
app/post/[postID]/(post)/components/Reply.tsx Hardens external-link confirm flow (protocol validation, HTML escaping, noopener).
app/ping/route.ts Moves version fetching server-side; expands backend version shape; adds logging.
app/page.tsx Import reordering.
app/new/page.tsx Adds localStorage schema validation/sanitization for persisted draft data.
app/layout.tsx Import reordering.
app/info/page.tsx Import reordering.
app/info/(Info)/mobile/index.tsx Formatting tweaks; uptime display refactor.
app/info/(Info)/desktop/index.tsx Formatting tweaks; uptime display refactor.
app/info/(Info)/config/data.json Renames a menu section and adds Changelog link.
app/device.tsx Import reordering.
app/data/page.tsx Import reordering.
app/data/(Data)/mobile/index.tsx Import reordering.
app/data/(Data)/desktop/index.tsx Import reordering.
app/dashboard/page.tsx Import reordering.
app/dashboard/(Dashboard)/Mobile/index.tsx Adds abort controllers + error logging to fetches.
app/dashboard/(Dashboard)/Desktop/index.tsx Adds abort controllers + error logging to fetches.
app/confirm/page.tsx Adds abort controller wiring to confirm request.
app/changelog/page.tsx New changelog route with mobile/desktop split.
app/changelog/(Changelog)/mobile/index.tsx New mobile changelog UI rendering JSON entries.
app/changelog/(Changelog)/mobile/index.module.scss New styles for mobile changelog layout.
app/changelog/(Changelog)/desktop/index.tsx New desktop changelog UI rendering JSON entries.
app/changelog/(Changelog)/config/changelog.json New changelog content source.
app/api/version/route.ts New server route to fetch main/development versions from GitHub.
app/api/auth/[...nextauth]/route.ts Import cleanup/reordering (also removed a stray profile import).
app/admin/sig-members/page.tsx Import reordering + formatting.
app/admin/sig-members/[sigID]/page.tsx Formatting improvements.
app/admin/sig-leader/page.tsx Import reordering + formatting.
app/admin/sig-leader/[sigID]/page.tsx Formatting improvements.
app/admin/sig-advisor/page.tsx Import reordering + formatting.
app/admin/sig-advisor/[sigID]/page.tsx Formatting improvements.
app/admin/post/page.tsx Import reordering + formatting.
app/admin/post-query/page.tsx Import reordering + formatting.
app/admin/page.tsx Import reordering + formatting.
app/[userID]/page.tsx Adds userID validation/sanitization + abort support for account fetches.
app/[userID]/(User)/mobile/info/index.tsx Hardens external-link confirm flow (protocol validation, escaping, noopener).
app/[userID]/(User)/mobile/index.tsx Import reordering.
app/[userID]/(User)/desktop/Info/index.tsx Hardens external-link confirm flow (protocol validation, escaping, noopener).
app/(Layout)/mobile/ToolBar/index.tsx Import reordering.
app/(Layout)/mobile/HeaderBar/UserLogin/index.tsx Import reordering.
app/(Layout)/mobile/HeaderBar/index.tsx Import reordering.
app/(Layout)/desktop/ToolBar/index.tsx Import reordering.
app/(Layout)/desktop/HeaderBar/index.tsx Import reordering.
app/(home)/mobile/ThreadsList.tsx Import reordering.
app/(home)/mobile/SigList.tsx Import reordering.
app/(home)/desktop/Information.tsx Import reordering.
AGENTS.md Adds an AI agent guide for repo conventions and structure.
.env.local.example Replaces NEXT_PUBLIC_GITHUB_TOKEN with server-only GITHUB_TOKEN.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/ping/route.ts
Comment thread app/ping/route.ts Outdated
Comment thread app/api/auth/[...nextauth]/route.ts Outdated
Comment thread app/new/page.tsx Outdated
Comment thread app/new/page.tsx
Comment thread AGENTS.md Outdated
Copy link
Copy Markdown
Member

@OnCloud125252 OnCloud125252 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — v2.19.0

Overview

This is a well-targeted security release. The four main themes are:

  1. Security hardening — GitHub token exposure fix, XSS prevention, URL/input validation
  2. Memory leak preventionAbortController + isMounted patterns across fetch calls
  3. New feature — Changelog page (desktop + mobile) and /api/version route
  4. Code formatting — Biome formatter applied (import sorting, JSX line breaks)

Security Analysis ✅

The security work here is excellent:

  • NEXT_PUBLIC_GITHUB_TOKENGITHUB_TOKEN: Critical fix. The old token was exposed to every browser client via Next.js's NEXT_PUBLIC_ prefix. Moving it to a server-only env var with /api/version as a proxy is the correct approach.
  • XSS prevention in JumpOut: URL protocol allowlisting, HTML escaping, and noopener,noreferrer are solid.
  • Validation module (modules/validation/index.ts): Well-structured with ObjectId, custom ID, and path traversal sanitization.
  • localStorage validation: Good defensive practice to validate parsed JSON shape before trusting it.

Issues Found

# Severity Issue
1 🔴 Bug useFetch dependency on options object will cause infinite re-render loops
2 🟡 DRY JumpOut function copy-pasted identically in 3 files
3 🟡 DRY getMainVersion() / getDevelopmentVersion() duplicated in 2 route files
4 🟢 Minor Unused useRef import in Dashboard components
5 🟢 Minor Unused urlObj variable assignments in JumpOut (linter may flag)

See inline comments for details.

Recommendation

Please fix the useFetch infinite loop bug (#1) before merging — it will break any component using useFetch with options. The DRY issues (#2, #3) are strongly recommended but not blocking. The rest is solid work 👍

Comment thread utils/useFetch/index.ts Outdated
Comment thread app/[userID]/(User)/desktop/Info/index.tsx Outdated
Comment thread app/api/version/route.ts Outdated
Comment thread app/[userID]/(User)/desktop/Info/index.tsx Outdated
Comment thread app/dashboard/(Dashboard)/Desktop/index.tsx Outdated
… leak

Module-scope QueryClient was shared across all SSR requests, causing
cache entries to accumulate in the Node.js process indefinitely. Moving
creation into useState ensures each SSR request gets an isolated instance
that is garbage-collected when the response completes.
config() from md-editor-rt was being called at module scope in layout.tsx,
a Server Component, pulling a client-side library into the server bundle
and letting its global state persist in the Node.js process. Extracted
to a dedicated 'use client' module imported only by the components that
actually render the editor.
sweetalert2 was imported but never used in the NextAuth route, adding
a client-side DOM library to the server bundle unnecessarily. Also added
.catch() to the fire-and-forget axios call in the webhook route to prevent
unhandled promise rejections from accumulating under login traffic.
Condense AGENTS.md into a concise quick-reference, add CLAUDE.md and
GEMINI.md as mirrors, and move detailed content into docs/ subdirectory.
Replace the brief technical description with a structured README
including a banner, feature list, usage guide, FAQ, and tech stack
summary in Traditional Chinese.
@zeabur zeabur Bot temporarily deployed to production April 7, 2026 00:25 Inactive
…pecifiers

Update the biome script from `lint` to `check --fix --unsafe` for more
comprehensive linting, and update AGENTS.md to reflect the new command.
Switch to Node.js built-in module specifiers (`node:path`, `node:assert`).
Add missing dependencies to useEffect hooks across dashboard, info, post
editor, and utility hooks to prevent stale closure bugs. Fix useLocalStorage
to include key in the setValue callback dependency and drive the effect off
setValue. Restore isLogin as a dep in useUserAccount despite the comment,
and remove userData from edit page's redundant dep.
- Replace string concatenation with template literals in class names
- Use optional chaining (?.) instead of short-circuit logical-and
- Prefix unused variables/catch bindings with underscore (_error, _res, etc.)
- Remove unused imports (React, Link, Fragment, useRef, unused hooks)
- Add explicit radix 10 to parseInt() calls
- Replace new Date().getTime() with Date.now()
- Remove redundant Fragment wrapper elements
- Remove !important from CSS editor wrapper rule
- Extract jumpOut URL validation utility from 4 duplicate implementations
- Extract getBranchVersion API module from 2 duplicate implementations
- Remove unused variables, imports, and dead functions
- Stabilize React state and fix useEffect dependencies
- Replace node:assert with standard error handling in client code
- Parallelize sequential API calls in user page
Add comprehensive Biome config with sorted classes, noForEach,
noConsole, noExplicitAny, block statements, and early return rules.
Pin all dependency versions and add before-push script.
Document enforced and intentionally-off Biome rules to guide
code generation and prevent lint violations.
Sort Tailwind classes, replace forEach with for-of, add block
statements, remove else-after-return, replace any types with
specific types, and remove bare console.log calls.
Use nullish coalescing for sig._id lookup and mark InfiniteData as
optional to prevent undefined key access and prop type mismatches.
Adds a .githooks/pre-push script that runs install, format/lint,
type-check, and build before every push. The prepare script wires
it up automatically via git config core.hooksPath.
Pre-push now runs gitleaks, env-secret detection, console.log check,
and bundle-size validation in addition to install/lint/type/build.
Post-merge skips pnpm install when lockfile is unchanged, cleans
.next cache on next.config changes, and warns on .env.local.example
updates.
Introduces scripts/prepare.mjs which sets the hooksPath and auto-creates
.env.local from the example on first install. Removes framer-motion,
jwt-decode, and react-cookie (unused after dead-code cleanup). Drops
stale turbopack resolveAlias. Updates AGENTS.md commands accordingly.
Next.js 15 passes route params as Promise<{…}>; using use(params)
at the top of the component unwraps it synchronously-safely and
removes the now-redundant inline destructures throughout the file.
Deletes thirteen orphaned files (APIs, utils, SCSS, modules) that are
no longer imported anywhere. Removes CustomCode enum, isValidSigId,
isValidUUID, and isMingdaoEmail which had no remaining callers.
Unexports the Thread component since it is only used within its file.
Disables animations and transitions for users who have requested
reduced motion, improving accessibility compliance.
@zeabur zeabur Bot temporarily deployed to production April 7, 2026 04:09 Inactive
Copy link
Copy Markdown
Member

@OnCloud125252 OnCloud125252 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: v2.19.0

Critical Issues

1. parseInt("0x34e718", 10) returns 0 — breaks Discord webhook color

The radix parameter 10 forces decimal parsing. Since "0x34e718" starts with "0x" (invalid in base-10), parseInt returns 0. The original code without radix correctly auto-detected the hex prefix.

Fix: Remove the radix, or use 0x34e718 directly as a number literal.

2. useUserAccountisLogin re-added to dependency array (potential infinite loop)

The comment says "移除 isLogin 依賴避免循環" but the code adds isLogin back into the dependency array. This was previously identified as the cause of an infinite fetch loop. Adding it back risks re-introducing that bug.

3. Unsafe (error as Error).message without instanceof check

Two catch blocks cast error: unknown directly to Error without checking instanceof. If the thrown value is a string or other non-Error, this produces new Error(undefined). Use error instanceof Error ? error.message : String(error) like other files in this PR.

Positive Highlights

  • Great security improvements (XSS, URL validation, token handling)
  • Systematic any elimination across all admin pages
  • <img><Image> migration with proper unoptimized flags
  • type="button" on all non-form buttons
  • AbortController for proper fetch cleanup
  • Comprehensive git hooks and changelog system

Recommendation: Fix issues #1 and #2 before merging.

Comment thread app/api/webhook/login/route.ts Outdated
Comment thread utils/useUserAccount/index.ts
Comment thread utils/useUserAccount/index.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 119 out of 123 changed files in this pull request and generated 16 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

app/post/[postID]/(post)/mobile/Replies.tsx:177

  • The send button is type="button" and has no onClick, so clicking it will not submit the form (only pressing Enter will). Change it to type="submit" or wire an onClick that calls handleCommandSubmit/submits the form.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread utils/useUserAccount/index.ts Outdated
Comment thread utils/useUserAccount/index.ts
Comment thread utils/useUserAccount/index.ts
Comment thread utils/usePost/index.ts Outdated
Comment thread app/post/[postID]/(post)/desktop/ThreadInfo.tsx
Comment thread docs/features.md
Comment thread docs/features.md Outdated
Comment thread docs/architecture.md
Comment thread docs/architecture.md
Comment thread package.json
Code fixes:
- Fix parseInt radix bug in webhook (0x parsed as base-10 → hex literal)
- Remove isLogin from useUserAccount deps to prevent infinite loop
- Use instanceof check for error handling in platformLogin
- Validate accessToken before passing to platformLogin
- Fix cover validation in new post page (accept image IDs, not just URLs)
- Use shared isValidObjectId instead of duplicated regex
- Change send button to type="submit" in ThreadInfo
- Fix broken Tailwind class overflow-y- → overflow-y-auto
- Set notfound state on fetch error in post page
- Use token prop in desktop Editor instead of redundant useUserAccount
- Filter failed uploads in mobile Editor to prevent invalid URLs
- Use [queryClient] instead of [queryClient.removeQueries] in usePost

Doc fixes:
- Update lint command from pnpm lint → pnpm check
- Replace removed useFetch.ts example with useIsMobile.ts
- Update features.md to reference TanStack Query hooks
- Remove non-existent validation helpers from docs
- Update Biome version to match package.json
- Update stale module list in architecture

Bump version from 2.18.8 to 2.19.0
@zeabur zeabur Bot temporarily deployed to production April 7, 2026 05:08 Inactive
@OnCloud125252
Copy link
Copy Markdown
Member

Review Feedback Addressed

All 30 review threads have been resolved in commit 61ef2f8.

# File Line Action Status
1 app/ping/route.ts L42 Remove success log spam Already fixed in prior commit
2 app/ping/route.ts Deduplicate version fetchers Already extracted to modules/api/getBranchVersion
3 app/api/auth/[...nextauth]/route.ts Remove unused imports Already removed in prior commit
4 app/new/page.tsx L71 Cover validation accepts IDs not just URLs Fixed
5 app/new/page.tsx L53 Use shared isValidObjectId Fixed
6 utils/useFetch/index.ts Infinite re-render loop File removed entirely
7 app/[userID]/desktop/Info/index.tsx Deduplicate JumpOut Already extracted to utils/jumpOut
8 app/api/version/route.ts Deduplicate version fetchers Already extracted to shared module
9 app/[userID]/desktop/Info/index.tsx Unused urlObj variable Fixed in extracted utility
10 app/dashboard/Desktop/index.tsx Unused useRef import Already removed
11 app/api/webhook/login/route.ts L13 parseInt("0x...", 10)0 bug Fixed: now uses hex literal
12 utils/useUserAccount/index.ts L76 isLogin in deps causes infinite loop Fixed: removed from deps
13 utils/useUserAccount/index.ts L131 Unsafe error as Error casting Fixed: instanceof check
14 utils/useUserAccount/index.ts L50 Unsafe accessToken assertion Fixed: type validation before use
15 utils/useUserAccount/index.ts L133 Same error casting (copilot) Fixed (same as #13)
16 utils/useUserAccount/index.ts L76 Same isLogin deps (copilot) Fixed (same as #12)
17 utils/usePost/index.ts L16 Brittle removeQueries dep Fixed: [queryClient]
18 ThreadInfo.tsx L218 Send button type="button" Fixed: type="submit"
19 ThreadInfo.tsx L180 Invalid overflow-y- class Fixed: overflow-y-auto
20 app/post/[postID]/page.tsx L66 Error state not set on failure Fixed: setStatus("notfound")
21 PostEditor/desktop/Editor.tsx L26 Token prop ignored Fixed: uses prop, removed hook call
22 PostEditor/mobile/Editor.tsx L42 Invalid URL on upload failure Fixed: filter failed uploads
23 docs/code-style.md L45 pnpm lint doesn't exist Fixed: pnpm check
24 docs/code-style.md L10 References removed useFetch.ts Fixed: useIsMobile.ts
25 docs/features.md L31 References removed useFetch hook Fixed: TanStack Query hooks
26 docs/features.md L58 Lists non-existent helpers Fixed: removed from docs
27 docs/architecture.md L17 Biome v2.2.5 → v2.3.13 Fixed
28 docs/architecture.md L74 Stale module list Fixed: matches current modules/
29 package.json L4 Version downgrade 2.18.82.19.0 Fixed

Build: passes | Biome check: passes | Type check: passes

Copy link
Copy Markdown
Member

@OnCloud125252 OnCloud125252 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@HACO8888 HACO8888 merged commit a35b395 into main Apr 7, 2026
4 checks passed
HACO8888 added a commit that referenced this pull request Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants